    //
//  ActiveView.m
//  CHAD
//
//  Created by Robin Mahony on 11-02-17.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

/*	
 Revision History: 
 
 Date     Author       Version   Changes
 ======== ============ ========= ================================================================
 02/18/11 Robin Mahony 1.0		Initial version.
 02/24/11 Robin Mahony 1.1		added new buttons and button methods.  also implemented scheme to
								handle knowning which buttons are being pressed, and modifying "controlString"
								accordingly.  This int will be sent to board and interpreted for use with
								controlling the robot and camera
 03/13/11 Robin/Bapi   2.0		Implemented socket communication.  also, updated controls and control methods
 03/23/11 Robin/Bapi   3.0		implemeted audio ability.  holding record button records, releasing record  
                                button stops the recording.  currently audio from movie silenced while
                                recording, but comes back once recording is done
 04/7/11 Robin		   3.1		Added back to MenuView option in activeView.  also, check for successful socket
								connection now done, and if failed go back to MenuView.  added exit button to main
								menu.  Also, ActiveView can now access any of its viewControllers methods, by using
								"myParent" ie. [myParent backToMenuView].
								Bug Fixes: -AlertView pop-up for socket disconnect would occur when socket failed
								to connect, and again after "Ok" was pressed (used disconnectFlag)
								-also, if quit ActiveView before socket connection failure occured, was trying
								to quit to MenuView after it had already quit to MenuView, causing a crash
								(solved using disconnectFlag)
 04/19/11 Robin       4.0		Removed movie player; added audio communication with beagleboard using second socket;
								added tactile feedback option to controls and better highlight buttons when
								touched; when app sleeps or is in background, now disconnect socket and exit to menu;
							
 ======== ============ ========= ================================================================
 
 */

#import "ActiveView.h"
#import "AsyncSocket.h"
#import "CustomMoviePlayerViewController.h"
#import <AudioToolbox/AudioServices.h>
#import <AudioToolbox/AudioToolbox.h>



//transform values for full screen support
#define CAMERA_TRANSFORM_X 1
#define CAMERA_TRANSFORM_Y 1.12412
//iphone screen dimensions
#define SCREEN_WIDTH  320
#define SCREEN_HEIGTH 480

#define timerInterval 0.03


@implementation ActiveView

@synthesize upCamButton, downCamButton, leftCamButton, rightCamButton,centerCamButton, backButton;
@synthesize upRobotButton, downRobotButton, leftRobotButton, rightRobotButton;
@synthesize exitFlag, disconnectFlag, tactileOption, contCamFlag;
@synthesize webView, refreshWebview;
//@synthesize myWriteStream;

-(void)awakeFromNib{

	NSLog(@"entered awake from nib, in ActiveView");

	playButton.enabled = NO;
	exitFlag = 0;
	disconnectFlag = 0;
	contCamFlag = 0;
	tactileOption = 1;
	//stopButton.enabled = NO;
	
	//Initialize audio recording stuff
	
	NSArray *dirPaths;
	NSString *docsDir;
	
	dirPaths = NSSearchPathForDirectoriesInDomains(
												   NSDocumentDirectory, NSUserDomainMask, YES);
	docsDir = [dirPaths objectAtIndex:0];
	NSString *soundFilePath = [docsDir
							   stringByAppendingPathComponent:@"sound.aac"];
	
	NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
	
	NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
	
	
	//save as .wav
	//[recordSettings setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
	
	//saves as .aac
	[recordSettings setValue :[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
	[recordSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; 
	[recordSettings setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
	
	[recordSettings setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
	[recordSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
	[recordSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
/*	
	
	NSDictionary *recordSettings = [NSDictionary 
									dictionaryWithObjectsAndKeys:
									[NSNumber numberWithInt:AVAudioQualityMin],
									AVEncoderAudioQualityKey,
									[NSNumber numberWithInt:16], 
									AVEncoderBitRateKey,
									[NSNumber numberWithInt: 2], 
									AVNumberOfChannelsKey,
									[NSNumber numberWithFloat:44100.0],
									AVSampleRateKey,
									nil];*/
	//AVFormatIDKey = kAudioFormatMPEGLayer3
	//									AVFormatIDKey,[NSNumber numberWithInt:kAudioFormatLinearPCM ],
	//[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];

	
	NSError *error = nil;
	
	audioRecorder = [[AVAudioRecorder alloc]
					 initWithURL:soundFileURL
					 settings:recordSettings
					 error:&error];
	
	if (error)
	{
		NSLog(@"error: %@", [error localizedDescription]);
		
	} else {
		[audioRecorder prepareToRecord];
	}

}



@synthesize playButton,  recordButton;
//@sythesize stopButton

/*
- (void)viewDidLoad {
	
}*/

-(void) recordAudio
{
	//magic line that allows recording and playing at same time
	[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
	
	//the following 2 lines are supposed to set property such that audio can be played back at normal
	//volume while recording audio (kAudioSessionProperty_OverrideCategoryMixWithOthers property).  
	//currently, audio playback is made quiet until recording is done
	//UInt32 doSetProperty = 1;
	//AudioSessionSetProperty (kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(doSetProperty), &amp;doSetProperty);
	
	
	NSLog(@"recording");
	if (!audioRecorder.recording)
	{	

		playButton.enabled = NO;
		//stopButton.enabled = YES;
		[audioRecorder record];
	}

	
/* the following lines are another way to set the kAudioSessionProperty_OverrideCategoryMixWithOthers property
 OSStatus propertySetError = 0;
 
 UInt32 allowMixing = true;
 propertySetError = AudioSessionSetProperty (
												
												kAudioSessionProperty_OverrideCategoryMixWithOthers,  // 1
												
												sizeof (allowMixing),                                 // 2
												
												&allowMixing                                          // 3
												};*/


}

//on release of the record button, this method is called to stop the recording
-(void)stop
{
	NSLog(@"Stop");
    //stopButton.enabled = NO;
    playButton.enabled = YES;
    recordButton.enabled = YES;
	
    if (audioRecorder.recording)
    {
		[audioRecorder stop];
		[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    } else if (audioPlayer.playing) {
		[audioPlayer stop];
    }
	
	[self sendToAudioSocket]; 
}

//test method used to play audio.  will not be used in final app
-(void) playAudio
{
	NSLog(@"start of playAudio");
    if (!audioRecorder.recording)
    {
		NSLog(@"audioRecording not recording, so play time");
		//stopButton.enabled = YES;
		recordButton.enabled = NO;
		
        if (audioPlayer)
			[audioPlayer release];
        NSError *error;
		
        audioPlayer = [[AVAudioPlayer alloc] 
					   initWithContentsOfURL:audioRecorder.url                                    
					   error:&error];
		
        audioPlayer.delegate = self;
		
        if (error)
			NSLog(@"Error: %@", 
				  [error localizedDescription]);
        else
		{
			NSLog(@"playing audio recording now");
			[audioPlayer play];
		}
	}
	
	
	[self sendToAudioSocket];
}

-(void)audioPlayerDidFinishPlaying:
(AVAudioPlayer *)player successfully:(BOOL)flag
{
	recordButton.enabled = YES;
	//stopButton.enabled = NO;
}
-(void)audioPlayerDecodeErrorDidOccur:
(AVAudioPlayer *)player 
								error:(NSError *)error
{
	NSLog(@"Decode Error occurred");
}
-(void)audioRecorderDidFinishRecording:
(AVAudioRecorder *)recorder 
						  successfully:(BOOL)flag
{
}
-(void)audioRecorderEncodeErrorDidOccur:
(AVAudioRecorder *)recorder 
								  error:(NSError *)error
{
	NSLog(@"Encode Error occurred");
}



/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/

/*
- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc. that aren't in use.
}*/

- (void)viewDidUnload {
	audioPlayer = nil;
	audioRecorder = nil;
	//stopButton = nil;
	recordButton = nil;
	playButton = nil;
	
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


-(IBAction)leftRobotTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}


	int x = 8; //"00001000" 
	
	//button pressed
	//first ensure no other robot buttons are active, bitwise and with "11110000"
	controlString = controlString &  240;
	// bitwise OR, add leftRobot
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"left robot button being touched, controlString = %i", controlString);
	
}

-(IBAction)upRobotTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 4; //"00000100" 
	
	//button pressed
	//first ensure no other robot buttons are active, bitwise and with "11110000"
	controlString = controlString &  240;
	// bitwise OR, add upRobot
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"up robot being touched, controlString = %i", controlString);

	
}


-(IBAction)rightRobotTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 2; //"00000010" 
	
	//button pressed
	//first ensure no other robot buttons are active, bitwise and with "11110000"
	controlString = controlString &  240;
	// bitwise OR, add rightRobot
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"right robot being touched, controlString = %i", controlString);
	
}

-(IBAction)downRobotTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 1; //"000000001" 
	
	//button pressed
	//first ensure no other robot buttons are active, bitwise and with "11110000"
	controlString = controlString &  240;
	// bitwise OR, add downRobot
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"down robot button being touched, controlString = %i", controlString);
	
}




-(IBAction)leftCamTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 128; //"10000000" 
	
	//button pressed
	//first ensure no other camera buttons are active, bitwise-and with "00001111"
	controlString = controlString &  15;
	// bitwise OR, add leftCam
	controlString = controlString |  x;
	/*myTimer =[NSTimer scheduledTimerWithTimeInterval:timerInterval
											  target:self selector:@selector(myTimerMethod)
											userInfo:nil repeats:YES];*/
	
	[self sendToSocket];
	NSLog(@"left cam button being touched, controlString = %i", controlString);
	
}


-(IBAction)upCamTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 64; //"01000000" 
	
	//button pressed
	//first ensure no other camera buttons are active, bitwise-and with "00001111"
	controlString = controlString &  15;
	// bitwise OR, add upCam
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"up cam button being touched, controlString = %i", controlString);
	
	/*myTimer =[NSTimer scheduledTimerWithTimeInterval:timerInterval
											  target:self selector:@selector(myTimerMethod)
											userInfo:nil repeats:YES];*/
	
}



-(IBAction)rightCamTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 32; //"00100000" 
	
	//button pressed
	//first ensure no other camera buttons are active, bitwise-and with "00001111"
	controlString = controlString &  15;
	// bitwise OR, add rightCam
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"right cam button being touched, controlString = %i", controlString);

	/*myTimer =[NSTimer scheduledTimerWithTimeInterval:timerInterval
											  target:self selector:@selector(myTimerMethod)
											userInfo:nil repeats:YES];*/
}


-(IBAction)downCamTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 16; //"00010000" 
	
	//button pressed
	//first ensure no other camera buttons are active, bitwise-and with "00001111"
	controlString = controlString &  15;
	// bitwise OR, add downCam
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"down cam button being touched, controlString = %i", controlString);
	
	/*myTimer =[NSTimer scheduledTimerWithTimeInterval:timerInterval
											  target:self selector:@selector(myTimerMethod)
											userInfo:nil repeats:YES]; */
}

-(IBAction)centerCamTouchDown{
	
	if(tactileOption == 1)
	{
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
	
	int x = 240; //"11110000" 
	
	//button pressed
	//first ensure no other camera buttons are active, bitwise-and with "00001111"
	controlString = controlString &  15;
	// bitwise OR, add centerCam
	controlString = controlString |  x;
	[self sendToSocket];
	NSLog(@"center cam button being touched, controlString = %i", controlString);
	
}

- (void) myTimerMethod{
	
	[self sendToSocket];
	
}

-(IBAction) camRelease{
	int x = 15; //"00001111" 
	//button released, bitwise AND, ensuring all camera movement stops
	controlString = controlString &  x;
	[self sendToSocket];
	NSLog(@"camera released, controlString = %i", controlString);

	//myTimer.invalidate;
	
}

-(IBAction) robotRelease{
	int x = 240; //"11110000" 
	//button released, bitwise AND, ensure all robot movement stops
	controlString = controlString &  x;
	[self sendToSocket];
	NSLog(@"robot released, controlString = %i", controlString);
	
}


/*
Still needs to be fixed so it actually works
 */
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
	
	if((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight))
	{
		return YES;
	}
	return NO;
}

//used to handle alert views
- (void) alertView: (UIAlertView *) alertView 
clickedButtonAtIndex: (NSInteger) buttonIndex 
{

	//called when exit button pressed
	if(alertView.tag == 1)
	{
		switch(buttonIndex)
		{
				
			case 0:
			{
				NSLog(@"exitFlag = %i", exitFlag);
				//exit to menu = YES;
				if(exitFlag == 0)
				{
					exitFlag = 1;
					[myParent backToMenuView];
				}
			}
				break;
				
			case 1:
			{
				//exit to menu = NO;
							}
				break;
				
			case 2: //toggle tactile feedback
			{
				tactileOption = 1 - tactileOption;
			}
				break;
				
		}
		
	}
	//Called when socket fails to connect
	else if(alertView.tag == 2)
	{
		switch(buttonIndex)
		{
			case 0:
			{
				NSLog(@"exitFlag = %i", exitFlag);
				if(exitFlag == 0)
				{
					
					exitFlag = 1;
					
					[myParent backToMenuView];
				}
			}
		}
	}

}

-(void)onSocketDidDisconnect: (AsyncSocket *)sock
{
	NSLog(@"socket failed to connect, in activeview. disconnectFlag = %i", disconnectFlag);
	
	//disconnectFlag = 1; //uncomment to disable auto quitting to menu on socket connection fail
	if(disconnectFlag == 0)
	{
		disconnectFlag = 1; //prevent this from being called more than once
		UIAlertView *alert = nil;
		alert = [[UIAlertView alloc] 
				initWithTitle:[NSString stringWithFormat:@"Error: Failed to establish socket connection!"]
				message:@"Will return to main menu"
				delegate:self 
				cancelButtonTitle:@"Ok" 
				otherButtonTitles:nil];
		alert.tag = 2;
		[alert show];
		[alert release];
	}
	

}

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
	NSLog(@"Socket connection established successfully");
}

- (void)connectToSocket{
	
	//NSError *errPtr;
	BOOL connectStatus = NO; //used to check if connection attempt succeeded
	//NSString *yourHostAsNSString =  @"127.0.0.1";
	//UInt16 yourPortAsInteger = 5000;
	//NSError **erPtr;
	//telemedix.dyndns.org
	testSocket = [[AsyncSocket alloc] initWithDelegate: self];
	//connectStatus = [testSocket connectToHost: @"192.168.0.107" onPort: 5000 error: nil];
	connectStatus = [testSocket connectToHost: @"telemedix.dyndns.org" onPort: 5000 error: nil];
	
	if(connectStatus == NO)
	{
		NSLog(@"Failed to attempt socket connection ");
		
	}
	
	else 
	{
		NSLog(@"Attempting to connect to socket");
	}
	
}

- (void)connectToAudioSocket{
	

	BOOL connectAudioStatus = NO; //used to check if connection attempt succeeded

	testAudioSocket = [[AsyncSocket alloc] initWithDelegate: self];

	//[testSocket connectToHost: @"192.168.1.70" onPort: 5000 error: nil];
	//connectStatus = [testSocket connectToHost: @"192.168.0.107" onPort: 5000 error: nil];
	connectAudioStatus = [testAudioSocket connectToHost: @"telemedix.dyndns.org" onPort: 6000 error: nil];
	
	if(connectAudioStatus == NO)
	{
		NSLog(@"Failed to attempt audio socket connection ");
		
	}
	else 
	{
		NSLog(@"Attempting to connect to audio socket");
	}
	
}

- (void)sendToSocket{	

	NSLog(@"sending to socket");
	NSData *dataToSend;
	NSString *stringToSend;
	
	stringToSend = [NSString stringWithFormat:@"%i#", controlString];	
	
	dataToSend = [stringToSend dataUsingEncoding: NSASCIIStringEncoding];
	
	[testSocket writeData: dataToSend withTimeout:-1 tag:0];
	
}

- (void)sendToAudioSocket{

	NSLog(@"sending to audio socket");
	NSData *dataToSend2;
	NSData *termChars;
	NSString *stringToSend2;
	
	stringToSend2 = [NSString stringWithFormat:@"##########"];
	
	//FOR SENDING AUDIO
	dataToSend2 = [[NSData alloc] initWithContentsOfURL:audioRecorder.url];

	NSLog(@"initialized data object with audio file");
	
	termChars = [stringToSend2 dataUsingEncoding: NSASCIIStringEncoding];
		
	[testAudioSocket writeData: dataToSend2 withTimeout:-1 tag:0];
	NSLog(@"audio written to socket");
	
	//send "####" to signify end of audio file
	[testAudioSocket writeData: termChars withTimeout:-1 tag:0];
	NSLog(@"terminating chars for audio file written to socket");
	[dataToSend2 release];
	
}

- (void)disconnectSocket{
	

	NSData *dataToSend, *dataToSendAudio;
	NSString *stringToSend, *stringToSendAudio;
	stringToSend = @"q";
	dataToSend = [stringToSend dataUsingEncoding: NSASCIIStringEncoding];
	[testSocket writeData:dataToSend withTimeout:-1 tag:0];
	
	stringToSendAudio = @"qqqqqqqqqq";
	dataToSendAudio = [stringToSendAudio dataUsingEncoding: NSASCIIStringEncoding];
	[testAudioSocket writeData:dataToSendAudio withTimeout:-1 tag:0];
	
	NSLog(@"disconnecting socket");
	[testSocket disconnectAfterWriting];
	[testAudioSocket disconnectAfterWriting];
	[testSocket release];
	[testAudioSocket release];

}

-(void)goToMainMenu{
	
	disconnectFlag = 1;
	
	if(tactileOption == 1)
	{
		UIAlertView *alert = nil;
		alert = [[UIAlertView alloc] 
				 initWithTitle:[NSString stringWithFormat:@"Options"]
				 message:@"Are you sure you wish to quit?"
				 delegate:self 
				 cancelButtonTitle:@"Quit" 
				 otherButtonTitles:@"Cancel",@"Turn Off Tactile Touch" ,nil];
		alert.tag = 1;
		[alert show];
		[alert release];
	}
	else 
	{
		UIAlertView *alert = nil;
		alert = [[UIAlertView alloc] 
				 initWithTitle:[NSString stringWithFormat:@"Options"]
				 message:@"Are you sure you wish to quit?"
				 delegate:self 
				 cancelButtonTitle:@"Quit" 
				 otherButtonTitles:@"Back",@"Turn On Tactile Touch" ,nil];
		alert.tag = 1;
		[alert show];
		[alert release];
		
	}

}




- (void)dealloc {
	NSLog(@"deallocating activeview");
	[audioPlayer release];
	[audioRecorder release];
//	[stopButton release];
	[playButton release];
	[recordButton release];

	
    [super dealloc];
}


@end
